import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;


public class Sprite {
	
	
	public String toString() {
		return "Sprite [tlx=" + tlx + ", tly=" + tly + ", width=" + width
				+ ", height=" + height + ", xloop=" + xloop + ", yloop="
				+ yloop + ", governingScreen=" + governingScreen + "]";
	}

	private BufferedImage spritePic;
	private double tlx;
	private double tly;
	private double xvel=0;
	private double yvel=0;
	private double xacc=0;
	private double yacc=0;
	private int xtermvel=200;
	private int ytermvel=200;
	private int width;
	private int height;
	private long curtime;
	private boolean xloop = true;
	private boolean yloop = true;
	private Screen governingScreen;
	private Rectangle rect;

	/**
	 * Creates a sprite with the specified image and position
	 * 
	 * @param governingScreen the screen which holds the sprite
	 * @param spritePic the image of the sprite
	 * @param tlx the top left x position of the sprite
	 * @param tly the top left y position of the sprite
	 */
	public Sprite(Screen governingScreen, BufferedImage spritePic, double tlx, double tly){
		this.curtime=System.currentTimeMillis();
		this.governingScreen=governingScreen;
		this.spritePic=spritePic;
		this.tlx=tlx;
		this.tly=tly;
		this.setWidth(spritePic.getWidth());
		this.setHeight(spritePic.getHeight());
		this.rect=new Rectangle((int)this.tlx,(int)this.tly,this.width,this.height);
	}

	/**
	 * Creates a sprite with the specified image, position, and velocities
	 * 
	 * @param governingScreen the screen which holds the sprite
	 * @param spritePic the image of the sprite
	 * @param tlx the top left x position of the sprite
	 * @param tly the top left y position of the sprite
	 * @param xvel the x velocity of the sprite
	 * @param yvel the y velocity of the sprite
	 */
	public Sprite(Screen governingScreen, BufferedImage spritePic, double tlx, double tly, double xvel, double yvel){
		this.curtime=System.currentTimeMillis();
		this.governingScreen=governingScreen;
		this.spritePic=spritePic;
		this.tlx=tlx;
		this.tly=tly;
		this.xvel=xvel;
		this.yvel=yvel;
		this.setWidth(spritePic.getWidth());
		this.setHeight(spritePic.getHeight());
		this.rect=new Rectangle((int)this.tlx,(int)this.tly,this.width,this.height);
	}

	/**
	 * Creates a sprite with the specified image, position, velocities, and accelerations
	 * 
	 * @param governingScreen the screen which holds the sprite
	 * @param spritePic the image of the sprite
	 * @param tlx the top left x position of the sprite
	 * @param tly the top left y position of the sprite
	 * @param xvel the x velocity of the sprite
	 * @param yvel the y velocity of the sprite
	 * @param xacc the x acceleration of the sprite
	 * @param yacc the y acceleration of the sprite
	 */
	public Sprite(Screen governingScreen, BufferedImage spritePic, double tlx, double tly, double xvel, double yvel, double xacc, double yacc){
		this.curtime=System.currentTimeMillis();
		this.governingScreen=governingScreen;
		this.spritePic=spritePic;
		this.tlx=tlx;
		this.tly=tly;
		this.xvel=xvel;
		this.yvel=yvel;
		this.xacc=xacc;
		this.yacc=yacc;
		this.setWidth(spritePic.getWidth());
		this.setHeight(spritePic.getHeight());
		this.rect=new Rectangle((int)this.tlx,(int)this.tly,this.width,this.height);
	}

	/**
	 * Creates a sprite with the specified image, position, velocities, accelerations, and terminal velocities
	 * 
	 * @param governingScreen the screen which holds the sprite
	 * @param spritePic the image of the sprite
	 * @param tlx the top left x position of the sprite
	 * @param tly the top left y position of the sprite
	 * @param xvel the x velocity of the sprite
	 * @param yvel the y velocity of the sprite
	 * @param xacc the x acceleration of the sprite
	 * @param yacc the y acceleration of the sprite
	 * @param xtermvel the terminal velocity in the x direction
	 * @param ytermvel the terminal velocity in the y direction
	 */
	public Sprite(Screen governingScreen, BufferedImage spritePic, double tlx, double tly, double xvel, double yvel, double xacc, double yacc, int xtermvel, int ytermvel){
		this.curtime=System.currentTimeMillis();
		this.governingScreen=governingScreen;
		this.spritePic=spritePic;
		this.tlx=tlx;
		this.tly=tly;
		this.xvel=xvel;
		this.yvel=yvel;
		this.xacc=xacc;
		this.yacc=yacc;
		this.xtermvel=xtermvel;
		this.ytermvel=ytermvel;
		this.setWidth(spritePic.getWidth());
		this.setHeight(spritePic.getHeight());
		this.rect=new Rectangle((int)this.tlx,(int)this.tly,this.width,this.height);
	}

	public void update(){
		long timediff = System.currentTimeMillis()-this.curtime;
		this.curtime=System.currentTimeMillis();
		this.tlx+=(this.xvel*((timediff+0.0)/(1000.0)));
		this.tly+=(this.yvel*((timediff+0.0)/(1000.0)));
		if(Math.abs(this.yvel+this.yacc*((timediff+0.0)/(1000.0)))<this.ytermvel){
			this.yvel+=this.yacc*((timediff+0.0)/(1000.0));
		}else{
			this.yvel=ytermvel;
		}
		if(Math.abs(this.xvel+this.xacc*((timediff+0.0)/(1000.0)))<this.xtermvel){
			this.xvel+=this.xacc*((timediff+0.0)/(1000.0));
		}else{
			this.xvel=xtermvel;
		}
		if(this.isXloop()){
			if(this.tlx>this.governingScreen.getWidth()+this.getWidth()){
				this.tlx=-this.getWidth();
			}
			else if(this.tlx<-this.getWidth()){
				this.tlx=this.governingScreen.getWidth()+this.getWidth();
			}
		}
		if(this.isYloop()){
			if(this.tly>this.governingScreen.getHeight()+this.getHeight()){
				this.tly=-this.getHeight();
			}
			else if(this.tly<-this.getHeight()){
				this.tly=this.governingScreen.getHeight()+this.getHeight();
			}
		}
		this.rect=new Rectangle((int)this.tlx,(int)this.tly,this.width,this.height);
	}

	public boolean isColliding(Sprite s){
		if(this.rect.intersects(s.rect)==false){
			return false;
		}
		for(int i=0;i<getWidth();i++){
			for(int j=0;j<getHeight();j++){
				int alpha = (new Color(spritePic.getRGB(i, j))).getAlpha();
				if(alpha>0){
					System.out.println(s.getTlx()+","+this.getTlx());
					double xdist=(s.getTlx()-this.getTlx());
					double ydist=(s.getTly()-this.getTly());
					int xToCheck=i-(int)xdist;
					int yToCheck=j-(int)ydist;
					if(xToCheck>=0 && yToCheck>=0 && xToCheck<s.getWidth() && yToCheck<s.getHeight()){
						if ((new Color(s.spritePic.getRGB(xToCheck, yToCheck))).getAlpha()>0){
							return true;
						}
					}
				}
			}
		}
		return false;
	}

	public void onCollision(){
		this.governingScreen.removeSprite(this);
	}

	public void paint(Graphics2D g){
		g.drawImage(getSpritePic(), null, (int)Math.round(getTlx()), (int)Math.round(getTly()));
	}






	//Getters and Setters
	/**
	 * @return the spritePic
	 */
	public BufferedImage getSpritePic() {
		return spritePic;
	}

	/**
	 * @param spritePic the spritePic to set
	 */
	public void setSpritePic(BufferedImage spritePic) {
		this.spritePic = spritePic;
	}

	/**
	 * @return the top left x position of the sprite
	 */
	public double getTlx() {
		return tlx;
	}

	/**
	 * @param tlx the top left x position of the sprite to set
	 */
	public void setTlx(int tlx) {
		this.tlx = tlx;
	}

	/**
	 * @return the top left y position of the sprite
	 */
	public double getTly() {
		return tly;
	}

	/**
	 * @param tly the top left y position of the sprite to set
	 */
	public void setTly(int tly) {
		this.tly = tly;
	}

	/**
	 * @return the width
	 */
	public int getWidth() {
		return width;
	}

	/**
	 * @param width the width to set
	 */
	private void setWidth(int width) {
		this.width = width;
	}

	/**
	 * @return the height
	 */
	public int getHeight() {
		return height;
	}

	/**
	 * @param height the height to set
	 */
	private void setHeight(int height) {
		this.height = height;
	}

	/**
	 * @return the xacc
	 */
	public double getXacc() {
		return xacc;
	}

	/**
	 * @param xacc the xacc to set
	 */
	public void setXacc(int xacc) {
		this.xacc = xacc;
	}

	/**
	 * @return the yacc
	 */
	public double getYacc() {
		return yacc;
	}

	/**
	 * @param yacc the yacc to set
	 */
	public void setYacc(int yacc) {
		this.yacc = yacc;
	}

	/**
	 * @return the xtermvel
	 */
	public int getXtermvel() {
		return xtermvel;
	}

	/**
	 * @param xtermvel the xtermvel to set
	 */
	public void setXtermvel(int xtermvel) {
		this.xtermvel = xtermvel;
	}

	/**
	 * @return the ytermvel
	 */
	public int getYtermvel() {
		return ytermvel;
	}

	/**
	 * @param ytermvel the ytermvel to set
	 */
	public void setYtermvel(int ytermvel) {
		this.ytermvel = ytermvel;
	}

	/**
	 * @return the xloop
	 */
	public boolean isXloop() {
		return xloop;
	}

	/**
	 * @param xloop the xloop to set
	 */
	public void setXloop(boolean xloop) {
		this.xloop = xloop;
	}

	/**
	 * @return the yloop
	 */
	public boolean isYloop() {
		return yloop;
	}

	/**
	 * @param yloop the yloop to set
	 */
	public void setYloop(boolean yloop) {
		this.yloop = yloop;
	}
}
